// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GOOGLE_PROTOBUF_EXPECTATION_PROTO_KIT_GENERATOR_H_
#define GOOGLE_PROTOBUF_EXPECTATION_PROTO_KIT_GENERATOR_H_

#include <string>

#include "google/protobuf-expectation/stubs/macros.h"
#include "google/protobuf/compiler/code_generator.h"

namespace google {
namespace protobuf {

class Descriptor;
class DescriptorProto;
class FieldDescriptor;
class FieldDescriptorProto;
class FileDescriptor;
class FileDescriptorProto;
class Message;

}  // namespace protobuf
}  // namespace google

namespace google {
namespace protobuf_expectation {

class ProtoKitGenerator : public google::protobuf::compiler::CodeGenerator {
 public:
  ProtoKitGenerator() {}

  // Implements the Generate() method defined as a pure virtual method
  // in the CodeGenerator abstract interface.
  // It generates proto kit for messages in the file descriptor and write it
  // as a proto file through the generator_context.
  bool Generate(const protobuf::FileDescriptor* file,
                const std::string& unused_parameter,
                google::protobuf::compiler::GeneratorContext* generator_context,
                std::string* error) const;

  // It's similar to Generate() method above but it generates proto kit and
  // returns it in a file descriptor proto.
  bool GenerateDescriptorProto(
      const protobuf::FileDescriptor* file,
      protobuf::FileDescriptorProto* output,
      std::string* error) const;

 private:
  bool ProcessFileDescriptor(
      const protobuf::FileDescriptor* file_descriptor,
      protobuf::FileDescriptorProto* output,
      std::string* error) const;
  bool ProcessDescriptor(
      const protobuf::Descriptor* descriptor,
      const std::string& field_name_to_add,
      protobuf::Message* output,
      std::string* error) const;
  bool FillProtoKit(
      const protobuf::Descriptor* descriptor,
      protobuf::DescriptorProto* output,
      std::string* error) const;
  bool FillRepeatedProtoKit(
      const protobuf::Descriptor* descriptor,
      protobuf::DescriptorProto* output,
      std::string* error) const;
  bool ProcessFieldDescriptor(
      const protobuf::FieldDescriptor* field_descriptor,
      protobuf::FieldDescriptorProto* output,
      std::string* error) const;

  DISALLOW_COPY_AND_ASSIGN(ProtoKitGenerator);
};

}  // namespace protobuf_expectation
}  // namespace google

#endif  // GOOGLE_PROTOBUF_EXPECTATION_PROTO_KIT_GENERATOR_H_
